//
//  CDRefreshControl.swift
//  XLWB
//
//  Created by MacBook on 16/7/7.
//  Copyright © 2016年 MacBook. All rights reserved.
//

import UIKit

//刷新控件的临界点
private let CDRefreshOffset: CGFloat = 60
//刷新状态
// - Normal:      普通状态，什么都不做
// - Pulling:     超过临界点，如果放手，开始刷新
// - WillRefresh: 用户超过临界点，并且放手

enum CDRefreshState {
    case Normal
    case Pulling
    case WillRefresh
}
class CDRefreshControl: UIControl {

    // MARK: - 属性
    /// 刷新控件的父视图，下拉刷新控件应该适用于 UITableView / UICollectionView
    private weak var scrollView: UIScrollView?
    
    //新视图
    private lazy var refreshView: CDRefreshView = CDRefreshView.refreshView()
    
    
    // MARK: - 构造函数
    init() {
        super.init(frame: CGRect())
        
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        setupUI()
    }
    /**
     willMove addSubview 方法会调用
     - 当添加到父视图的时候，newSuperview 是父视图
     - 当父视图被移除，newSuperview 是 nil
     */
    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        
        // 判断父视图的类型
        guard let sv = newSuperview as? UIScrollView else {
            return
        }
        
        // 记录父视图
        scrollView = sv
        
        // KVO 监听父视图的 contentOffset
        scrollView?.addObserver(self, forKeyPath: "contentOffset", options: [], context: nil)
    }
    
    //本视图从俯视图上移除
    //所有的下拉刷新框架都是监听俯视图的contentOffset,所有框架的kvo监听实现思路都是这个
    override func removeFromSuperview() {
        
        superview?.removeObserver(self, forKeyPath: "contentOffset")
        
        
        
        super.removeFromSuperview()
    }
    
    
    
    
    // 所有 KVO 方法会统一调用此方法
    override func observeValue(forKeyPath keyPath: String?, of object: AnyObject?, change: [NSKeyValueChangeKey : AnyObject]?, context: UnsafeMutablePointer<Void>?) {
        
        // contentOffset 的 y 值跟 contentInset 的 top 有关
        //print(scrollView?.contentOffset)
        
        guard let sv = scrollView else {
            return
        }
        
        // 初始高度就应该是 0
        let height = -(sv.contentInset.top + sv.contentOffset.y)
        
        if height < 0 {
            return
        }
        
        
        // 可以根据高度设置刷新控件的 frame
        self.frame = CGRect(x: 0,
                            y: -height,
                            width: sv.bounds.width,
                            height: height)
        
        print(height)
        //判断临界点,只需要判断一次
        if sv.isDragging {
            
            if height > CDRefreshOffset && (refreshView.refreshState == .Normal) {
                print("放手开始刷新")
                refreshView.refreshState = .Pulling
            } else if height <= CDRefreshOffset && (refreshView.refreshState == .Pulling) {
            
                print("再使劲")
                refreshView.refreshState = .Normal
            
            }
        } else {
        
            print("放手")
            if refreshView.refreshState == .Pulling {
                
                print("准备开始刷新")
                
//                //刷新结束之后,将状态修改为.Normal 才能继续相应刷新

                beginRefreshing()
                //发送刷新数据事件
                sendActions(for: .valueChanged)
            }
        }
    }
    
    
    /// 开始刷新
    func beginRefreshing() {
        print("开始刷新")
        
        guard let sv = scrollView else {
            return
        }
        
        //判断是否正在刷新,如果正在刷新,直接返回
        if refreshView.refreshState == .WillRefresh {
            return
        }
        //设置刷新状态
        refreshView.refreshState = .WillRefresh
        //设置间距
        var inset = sv.contentInset
        inset.top += CDRefreshOffset
        
        //会触发表格的contentOffset的变化
        sv.contentInset = inset
    }
    
    /// 结束刷新
    func endRefreshing() {
        
        print("结束刷新")
        
        guard let sv = scrollView else {
            return
        }
        
        //判断状态,是否整在刷新,如果不是,直接返回
        if refreshView.refreshState != .WillRefresh {
            return
        }
        //恢复刷新视图的状态
        refreshView.refreshState = .Normal
        
        //恢复表格视图的contentInset
        var inset = sv.contentInset
        inset.top -= CDRefreshOffset
        sv.contentInset = inset
    }
}
extension CDRefreshControl {
        
        private func setupUI() {
            backgroundColor = UIColor.white()
            
            //设置超出边界不显示
//            clipsToBounds = true
            
            addSubview(refreshView)
            
            //自动布局
            refreshView.translatesAutoresizingMaskIntoConstraints = false
            
            addConstraint(NSLayoutConstraint(item: refreshView,
                                             attribute: .centerX,
                                             relatedBy: .equal,
                                             toItem: self,
                                             attribute: .centerX,
                                             multiplier: 1.0,
                                             constant: 0))
            addConstraint(NSLayoutConstraint(item: refreshView,
                                             attribute: .bottom,
                                             relatedBy: .equal,
                                             toItem: self,
                                             attribute: .bottom,
                                             multiplier: 1.0,
                                             constant: 0))
            addConstraint(NSLayoutConstraint(item: refreshView,
                                             attribute: .width,
                                             relatedBy: .equal,
                                             toItem: nil,
                                             attribute: .notAnAttribute,
                                             multiplier: 1.0,
                                             constant: refreshView.bounds.width))
            addConstraint(NSLayoutConstraint(item: refreshView,
                                             attribute: .height,
                                             relatedBy: .equal,
                                             toItem: nil,
                                             attribute: .notAnAttribute,
                                             multiplier: 1.0,
                                             constant: refreshView.bounds.height))

        }
    }


